/*
*
*/

#include <stdlib.h>
#include <stdio.h>

#define ds_screen_c
#define LUA_LIB

#include <lua.h>
#include <lauxlib.h>

#include <ulib/ulib.h>

#include "vars.h"
#include "microlualib.h"

static int screen_init(lua_State *L) {
    SCREEN_UP_DISPLAY = 0;
    SCREEN_DOWN_DISPLAY = 1;
    spaceBetweenScreens = 0;
    return 0;
}

static int screen_switch(lua_State *L) {
    int tmp = SCREEN_UP_DISPLAY;
    SCREEN_UP_DISPLAY = SCREEN_DOWN_DISPLAY;
    SCREEN_DOWN_DISPLAY = tmp;
    return 0;
}

static int screen_blit(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x, y;
    if(lua_isnumber(L, 2)) x = (int)luaL_checknumber(L, 2); else{ luaL_error(L, "x must be a number"); return 0;}
    if(lua_isnumber(L, 3)) y = (int)luaL_checknumber(L, 3); else{ luaL_error(L, "y must be a number"); return 0;}
    UL_IMAGE * img = lua_touserdata(L, 4);
    int sourcex=-1, sourcey=-1, width=-1, height=-1;
    if(lua_isnumber(L, 5)) sourcex = (int)luaL_checknumber(L, 5);
    if(lua_isnumber(L, 6)) sourcey = (int)luaL_checknumber(L, 6);
    if(lua_isnumber(L, 7)) width  = (int)luaL_checknumber(L, 7);
    if(lua_isnumber(L, 8)) height = (int)luaL_checknumber(L, 8);
    assert(L, screen == SCREEN_UP_DISPLAY || screen == SCREEN_DOWN_DISPLAY || screen == SCREEN_BOTH , "Bad screen number");
    assert(L, img != NULL, "Bad image ressource");
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        if(height != -1) ulSetImageTile(img, sourcex, sourcey, sourcex+width, sourcey+height);
        else{
            if(sourcey != -1) ulSetImageTile(img, sourcex, sourcey, img->sizeX, img->sizeY);
        }
        ulDrawImageXY(img, x+img->centerX, y+img->centerY);
        //ulResetImageTile(img);
    }
    return 0;
}

static int screen_getMainLcd(lua_State *L) {
    lua_pushboolean(L, ulGetMainLcd());
    return 1;
}

static int screen_startDrawing2D(lua_State *L) {
    ulStartDrawing2D();
    return 0;
}

static int screen_endDrawing(lua_State *L) {
    ulEndDrawing();
    return 0;
}

static int screen_waitForVBL(lua_State *L) {
    ulSyncFrame();
    return 0;
}

static int screen_print(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x = (int)luaL_checknumber(L, 2);
    int y = (int)luaL_checknumber(L, 3);
    char * text = (char *)luaL_checkstring(L, 4);
    int color = RGB15(31, 31, 31);
    if(lua_isnumber(L, 5)) color = (int)luaL_checknumber(L, 5);
    assert(L, screen == SCREEN_UP_DISPLAY || screen == SCREEN_DOWN_DISPLAY || screen == SCREEN_BOTH , "Bad screen number");
    /*assert(L, x>=0, "x must be >= 0");
    assert(L, y>=0, "y must be >= 0");*/
    assert(L, text != NULL , "Text can't be null");
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulSetTextColor(color);
        ulDrawString(x, y, text);
    }
    return 0;
}

static int screen_printFont(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x = (int)luaL_checknumber(L, 2);
    int y = (int)luaL_checknumber(L, 3);
    char * text = (char *)luaL_checkstring(L, 4);
    int color = RGB15(31, 31, 31);
    if(lua_isnumber(L, 5)) color = (int)luaL_checknumber(L, 5);
    UL_FONT * font = lua_touserdata(L, 6);
    assert(L, screen == SCREEN_UP_DISPLAY || screen == SCREEN_DOWN_DISPLAY || screen == SCREEN_BOTH , "Bad screen number");
    /*assert(L, x>=0, "x must be >= 0");
    assert(L, y>=0, "y must be >= 0");*/
    assert(L, text != NULL, "Text can't be null");
    assert(L, font != NULL, "Font can't be null");
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulSetFont(font);
        ulSetTextColor(color);
        ulDrawString(x, y, text);
        ulSetFont(ul_lcdFont);
    }
    return 0;
}

static int screen_drawLine(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x0 = (int)luaL_checknumber(L, 2);
    int y0 = (int)luaL_checknumber(L, 3);
    int x1 = (int)luaL_checknumber(L, 4);
    int y1 = (int)luaL_checknumber(L, 5);
    int color = (int)luaL_checknumber(L, 6);
    /*assert(L, x0>=0, "x0 must be >= 0");
    assert(L, y0>=0, "y0 must be >= 0");
    assert(L, x1>=0, "x1 must be >= 0");
    assert(L, y1>=0, "y1 must be >= 0");*/
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulDrawLine(x0, y0, x1, y1, color);
    }
    return 0;
}

static int screen_drawRect(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x0 = (int)luaL_checknumber(L, 2);
    int y0 = (int)luaL_checknumber(L, 3);
    int x1 = (int)luaL_checknumber(L, 4);
    int y1 = (int)luaL_checknumber(L, 5);
    int color = (int)luaL_checknumber(L, 6);
    /*assert(L, x0>=0, "x0 must be >= 0");
    assert(L, y0>=0, "y0 must be >= 0");
    assert(L, x1>=0, "x1 must be >= 0");
    assert(L, y1>=0, "y1 must be >= 0");*/
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulDrawRect(x0, y0, x1, y1, color);
    }
    return 0;
}

static int screen_drawFillRect(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x0 = (int)luaL_checknumber(L, 2);
    int y0 = (int)luaL_checknumber(L, 3);
    int x1 = (int)luaL_checknumber(L, 4);
    int y1 = (int)luaL_checknumber(L, 5);
    int color = (int)luaL_checknumber(L, 6);
    /*assert(L, x0>=0, "x0 must be >= 0");
    assert(L, y0>=0, "y0 must be >= 0");
    assert(L, x1>=0, "x1 must be >= 0");
    assert(L, y1>=0, "y1 must be >= 0");*/
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulDrawFillRect(x0, y0, x1, y1, color);
    }
    return 0;
}

static int screen_drawGradientRect(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x0 = (int)luaL_checknumber(L, 2);
    int y0 = (int)luaL_checknumber(L, 3);
    int x1 = (int)luaL_checknumber(L, 4);
    int y1 = (int)luaL_checknumber(L, 5);
    int color1 = (int)luaL_checknumber(L, 6);
    int color2 = (int)luaL_checknumber(L, 7);
    int color3 = (int)luaL_checknumber(L, 8);
    int color4 = (int)luaL_checknumber(L, 9);
    /*assert(L, x0>=0, "x0 must be >= 0");
    assert(L, y0>=0, "y0 must be >= 0");
    assert(L, x1>=0, "x1 must be >= 0");
    assert(L, y1>=0, "y1 must be >= 0");*/
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulDrawGradientRect(x0, y0, x1, y1, color1, color2, color3, color4);
    }
    return 0;
}

static int screen_drawTextBox(lua_State *L) {
    int screen = (int)luaL_checknumber(L, 1);
    int x0 = (int)luaL_checknumber(L, 2);
    int y0 = (int)luaL_checknumber(L, 3);
    int x1 = (int)luaL_checknumber(L, 4);
    int y1 = (int)luaL_checknumber(L, 5);
    char * text = (char *)luaL_checkstring(L, 6);
    int color = RGB15(31, 31, 31);
    if(lua_isnumber(L, 7)) color = (int)luaL_checknumber(L, 7);
    /*assert(L, x0>=0, "x0 must be >= 0");
    assert(L, y0>=0, "y0 must be >= 0");
    assert(L, x1>=0, "x1 must be >= 0");
    assert(L, y1>=0, "y1 must be >= 0");*/
    ulSetTextColor(color);
    if ((screen == SCREEN_UP_DISPLAY && ulGetMainLcd()) || (screen == SCREEN_DOWN_DISPLAY && !ulGetMainLcd()) || screen == SCREEN_BOTH){
        ulDrawTextBox(x0, y0, x1, y1, text, UL_PF_PAL8);
    }
    return 0;
}

static int screen_setSpaceBetweenScreens(lua_State *L) {
    spaceBetweenScreens = (int)luaL_checknumber(L, 1);
    return 0;
}

static const luaL_Reg screenlib[] = {
    {"init", screen_init},
    {"switch", screen_switch},
    {"getMainLcd", screen_getMainLcd},
    {"startDrawing2D", screen_startDrawing2D},
    {"endDrawing", screen_endDrawing},
    {"waitForVBL", screen_waitForVBL},
    {"print", screen_print},
    {"printFont", screen_printFont},
    {"blit", screen_blit},
    {"drawLine", screen_drawLine},
    {"drawRect", screen_drawRect},
    {"drawFillRect", screen_drawFillRect},
    {"drawGradientRect", screen_drawGradientRect},
    {"drawTextBox", screen_drawTextBox},
    {"setSpaceBetweenScreens", screen_setSpaceBetweenScreens},
    {NULL, NULL}
};

/*
** Open infos library
*/
LUALIB_API int luaopen_screen (lua_State *L) {
    luaL_register(L, LUA_SCREENLIBNAME, screenlib);
    return 1;
}
